﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace ChineseChess.Game.AI
{
    public class Score
    {
        public int score;
        public Piece pie;
        public int i;
        public int x;
        public int y;
        public Score(int score, Piece pie, int i, int x, int y)
        {
            this.i = i;
            this.score = score;
            this.pie = pie;
            this.x = x;
            this.y = y;
        }

    }

    public class BaseAi
    {

        public BaseAi()
        { 

        }

        public static int evaluate(List<Piece> pieceList,bool isred)
        {
            int score = 0;

            for (int i = 0; i < pieceList.Count; i++) 
            {
                var pie = pieceList[i];

                int x = pie.X;
                int y = isred ? pie.Y : 9 - pie.Y;
                
                if (pie.isRed == isred)
                {
                    score += (int)(score_table[pie.Name.ToString()][y][x] * 1.1);
                }
                else
                {
                    score -= (int)(score_table[pie.Name.ToString()][y][x] * 0.9);
                }
            }
            return score;
        }

        public static Piece MovePie(List<Piece> pieceList, Moves mv, out Moves historyMv)
        {
            //Piece hispie = CopyPiece(mv.pie);
            historyMv = new Moves(mv.pie, new Point(mv.pie.X, mv.pie.Y));
            Piece movedPie = clearPiece(pieceList, (int)mv.p.X, (int)mv.p.Y);
            //hispie.X = (int)mv.p.X;
            //hispie.Y = (int)mv.p.Y;
            mv.pie.X = (int)mv.p.X;
            mv.pie.Y = (int)mv.p.Y;
            return movedPie;
        }

        public static void BackMovePie(List<Piece> pieceList, Piece pie, Moves historyMv)
        {
            historyMv.pie.X = (int)historyMv.p.X;
            historyMv.pie.Y = (int)historyMv.p.Y;
            if (pie != null)
            {
                pieceList.Add(pie);
            }
        }

        public static List<Moves> generateMoves(List<Piece> pieceList, bool isRed)
        {
            List<Moves> mv = new List<Moves>();

            for (int i = 0; i < pieceList.Count; i++)
            {   //遍历走子
                var pie = pieceList[i];

                if (pie.isRed == isRed) //当前走的子,第一步， 黑子走
                {
                    List<Point> point = pie.rule.getNextPos(pie, pieceList); //该子下一步可走的点

                    for (int j = 0; j < point.Count; j++)
                    {
                        mv.Add(new Moves(pie, point[j]));
                    }
                }
            }

            return mv;
        }


        /// <summary>
        /// 吃掉某点的子
        /// </summary>
        /// <param name="pieceList"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public static Piece clearPiece(List<Piece> pieceList, int x, int y, bool isred = true)
        {
            for (int i = 0; i < pieceList.Count; i++)
            {
                var pie = pieceList[i];

                if (pie.X == x && pie.Y == y && pie.isRed == isred)
                {
                    pieceList.Remove(pie); //移除某子
                    pie.InvalidateVisual();
                    return pie;
                }
            }
            return null;
        }

        /// <summary>
        /// 吃掉某点的子
        /// </summary>
        /// <param name="pieceList"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public static Piece clearPiece(List<Piece> pieceList, int x, int y)
        {
            for (int i = 0; i < pieceList.Count; i++)
            {
                var pie = pieceList[i];

                if (pie.X == x && pie.Y == y)
                {
                    pieceList.Remove(pie); //移除某子
                    pie.InvalidateVisual();
                    return pie;
                }
            }
            return null;
        }

        public static Random rd = new Random();
        /// <summary>
        /// 判定某阵营当前状态的得分
        /// </summary>
        /// <param name="pieceList"></param>
        /// <returns></returns>
        public static int getScore(List<Piece> pieceList, bool isred = true)
        {
            int redScore = getCampScore(pieceList, true);
            int blcakScore = getCampScore(pieceList, false);

            if (isred)
            {
                return redScore - blcakScore;// + rd.Next(1,10);
            }
            else
            {
                return blcakScore - redScore;// + rd.Next(1, 10); 
            }
        }

        /// <summary>
        /// 获取某阵营的局面得分
        /// </summary>
        /// <returns></returns>
        public static int getCampScore(List<Piece> pieceList, bool isred = true)
        {
            int sum = 0;
            for (int i = 0; i < pieceList.Count; i++)
            {
                var pie = pieceList[i];
                if (pie.isRed == isred)
                {
                    sum += getPieceScore(pie);
                }
            }

            return sum;

            if (isred)
            {
                return (int)(sum * 0.9);
            }
            return (int)(sum * 1.1);
        }

        /// <summary>
        /// 获取某个子的价值
        /// </summary>
        /// <returns></returns>
        public static int getPieceScore(Piece pie)
        {
            if (pie.Name == ChessName.兵)
            {
                return 40;
            }
            else if (pie.Name == ChessName.士)
            {
                return 20;
            }
            else if (pie.Name == ChessName.将)
            {
                return 10000;
            }
            else if (pie.Name == ChessName.炮)
            {
                return 100;
            }
            else if (pie.Name == ChessName.象)
            {
                return 20;
            }
            else if (pie.Name == ChessName.车)
            {
                return 200;
            }
            else if (pie.Name == ChessName.马)
            {
                return 90;
            }
            return 0;
        }

        public static Dictionary<string, int[][]> score_table = new Dictionary<string, int[][]>();
        public static void initTable()
        {
            if (score_table.Count > 0)
            {
                return;
            }
            score_table.Add("将",
                new int[][]
                {
                    new int[] {0   ,0   ,0   ,9980,9999,9980,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,9970,9970,9970,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,9950,9950,9950,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   }
                });
            score_table.Add("士",
              new int[][]
              {
                    new int[] {0   ,0   ,0   ,200 ,0   ,200 ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,240 ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,200 ,0   ,200 ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   }
              });
            score_table.Add("象",
          new int[][]
          {
                    new int[] {0   ,0   ,210 ,0   ,0   ,0   ,210 ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {200 ,0   ,0   ,0   ,250 ,0   ,0   ,0   ,200 },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,200 ,0   ,0   ,0   ,200 ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   }
          });

            score_table.Add("兵",
             new int[][]
             {
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   ,0   },
                    new int[] {150 ,0   ,150 ,0   ,230 ,0   ,150 ,0   ,150 },
                    new int[] {140 ,0   ,170 ,0   ,200 ,0   ,170 ,0   ,140 },

                    new int[] {180 ,190 ,200 ,200 ,210 ,200 ,200 ,190 ,180 },
                    new int[] {180 ,190 ,200 ,210 ,210 ,210 ,200 ,190 ,180 },
                    new int[] {190 ,190 ,200 ,220 ,220 ,220 ,210 ,190 ,190 },
                    new int[] {170 ,180 ,200 ,230 ,230 ,230 ,200 ,180 ,170 },
                    new int[] {160 ,160 ,190 ,200 ,200 ,200 ,190 ,160 ,160 }
             });

            score_table.Add("车",
             new int[][]
             {
                    new int[] {1190,1240,1200,1200,1200,1200,1200,1240,1190},
                    new int[] {1200,1220,1200,1210,1200,1210,1200,1220,1200},
                    new int[] {1190,1220,1200,1200,1200,1200,1200,1220,1190},
                    new int[] {1210,1220,1200,1200,1200,1200,1200,1220,1210},
                    new int[] {1220,1250,1220,1260,1200,1260,1220,1250,1220},

                    new int[] {1230,1240,1230,1240,1230,1240,1230,1240,1230},
                    new int[] {1230,1230,1240,1230,1230,1230,1240,1230,1230},
                    new int[] {1230,1230,1230,1230,1240,1230,1230,1230,1230},
                    new int[] {1230,1240,1230,1230,1240,1230,1230,1240,1230},
                    new int[] {1250,1250,1230,1250,1240,1250,1230,1250,1250}
             });

            score_table.Add("马",
             new int[][]
             {
                    new int[] {450 ,500 ,500 ,480 ,470 ,480 ,500 ,500 ,450 },
                    new int[] {450 ,510 ,510 ,470 ,480 ,470 ,510 ,510 ,450 },
                    new int[] {500 ,500 ,540 ,510 ,500 ,510 ,540 ,500 ,500 },
                    new int[] {500 ,520 ,520 ,510 ,500 ,510 ,520 ,520 ,500 },
                    new int[] {500 ,530 ,540 ,530 ,520 ,530 ,540 ,530 ,500 },

                    new int[] {530 ,540 ,540 ,540 ,540 ,530 ,540 ,540 ,530 },
                    new int[] {530 ,530 ,540 ,530 ,530 ,530 ,540 ,530 ,530 },
                    new int[] {530 ,530 ,540 ,550 ,530 ,550 ,540 ,530 ,530 },
                    new int[] {520 ,530 ,550 ,530 ,530 ,530 ,550 ,530 ,520 },
                    new int[] {510 ,530 ,540 ,530 ,530 ,530 ,540 ,530 ,510 }
             });

            score_table.Add("炮",
             new int[][]
             {
                    new int[] {500 ,500 ,510 ,500 ,500 ,500 ,510 ,500 ,500 },
                    new int[] {500 ,500 ,500 ,500 ,500 ,500 ,500 ,500 ,500 },
                    new int[] {510 ,500 ,510 ,520 ,540 ,520 ,510 ,500 ,510 },
                    new int[] {500 ,500 ,500 ,500 ,550 ,500 ,500 ,500 ,500 },
                    new int[] {500 ,500 ,500 ,500 ,550 ,500 ,500 ,500 ,500 },

                    new int[] {510 ,510 ,510 ,510 ,550 ,510 ,510 ,510 ,510 },
                    new int[] {510 ,510 ,510 ,500 ,550 ,500 ,510 ,510 ,510 },
                    new int[] {510 ,500 ,510 ,500 ,500 ,500 ,510 ,500 ,510 },
                    new int[] {510 ,500 ,510 ,500 ,500 ,500 ,510 ,500 ,510 },
                    new int[] {550 ,540 ,500 ,500 ,500 ,500 ,500 ,540 ,550 }
             });

        }

        public static void initTable2()
        {
            if (score_table.Count > 0)
            {
                return;
            }
            score_table.Add("将",
                new int[][]
                {
                    new int[] {0, 0, 0, 8888, 8888, 8888, 0, 0, 0},
                    new int[] {0, 0, 0, 8888, 8888, 8888, 0, 0, 0},
                    new int[] {0, 0, 0, 8888, 8888, 8888, 0, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},

                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0, 0, 8888, 8888, 8888, 0, 0, 0},
                    new int[] {0, 0, 0, 8888, 8888, 8888, 0, 0, 0},
                    new int[] {0, 0, 0, 8888, 8888, 8888, 0, 0, 0 }
                });
            score_table.Add("士",
              new int[][]
              {
                    new int[] {0, 0, 0,20, 0,20, 0, 0, 0},
                    new int[] {0, 0, 0, 0,23, 0, 0, 0, 0},
                    new int[] {0, 0, 0,20, 0,20, 0, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},

                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0, 0,20, 0,20, 0, 0, 0},
                    new int[] {0, 0, 0, 0,23, 0, 0, 0, 0},
                    new int[] {0, 0, 0,20, 0,20, 0, 0, 0 }
              });
            score_table.Add("象",
          new int[][]
          {
                    new int[] {0, 0,20, 0, 0, 0,20, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0, 0, 0,23, 0, 0, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0,20, 0, 0, 0,20, 0, 0},

                    new int[] {0, 0,20, 0, 0, 0,20, 0, 0},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {18,0, 0, 0,23, 0, 0, 0,18},
                    new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0},
                    new int[] {0, 0,20, 0, 0, 0,20, 0, 0}
          });

            score_table.Add("兵",
             new int[][]
             {
                    new int[] { 9,  9,  9, 11, 13, 11,  9,  9,  9},
                    new int[] {19, 24, 34, 42, 44, 42, 34, 24, 19},
                    new int[] {19, 24, 32, 37, 37, 37, 32, 24, 19},
                    new int[] {19, 23, 27, 29, 30, 29, 27, 23, 19},
                    new int[] {14, 18, 20, 27, 29, 27, 20, 18, 14},

                    new int[] { 7,  0, 13,  0, 16,  0, 13,  0,  7},
                    new int[] { 7,  0,  7,  0, 15,  0,  7,  0,  7},
                    new int[] { 0,  0,  0,  0,  0,  0,  0,  0,  0},
                    new int[] { 0,  0,  0,  0,  0,  0,  0,  0,  0},
                    new int[] { 0,  0,  0,  0,  0,  0,  0,  0,  0 }
             });

            score_table.Add("车",
             new int[][]
             {
                    new int[] {206, 208, 207, 213, 214, 213, 207, 208, 206},
                    new int[] {206, 212, 209, 216, 233, 216, 209, 212, 206},
                    new int[] {206, 208, 207, 214, 216, 214, 207, 208, 206},
                    new int[] {206, 213, 213, 216, 216, 216, 213, 213, 206},
                    new int[] {208, 211, 211, 214, 215, 214, 211, 211, 208},

                    new int[] {208, 212, 212, 214, 215, 214, 212, 212, 208},
                    new int[] {204, 209, 204, 212, 214, 212, 204, 209, 204},
                    new int[] {198, 208, 204, 212, 212, 212, 204, 208, 198},
                    new int[] {200, 208, 206, 212, 200, 212, 206, 208, 200},
                    new int[] {194, 206, 204, 212, 200, 212, 204, 206, 194}
             });

            score_table.Add("马",
             new int[][]
             {
                    new int[] {90, 90, 90, 96, 90, 96, 90, 90, 90},
                    new int[] {90, 96,103, 97, 94, 97,103, 96, 90},
                    new int[] {92, 98, 99,103, 99,103, 99, 98, 92},
                    new int[] {93,108,100,107,100,107,100,108, 93},
                    new int[] {90,100, 99,103,104,103, 99,100, 90},

                    new int[] {90, 98,101,102,103,102,101, 98, 90},
                    new int[] {92, 94, 98, 95, 98, 95, 98, 94, 92},
                    new int[] {93, 92, 94, 95, 92, 95, 94, 92, 93},
                    new int[] {85, 90, 92, 93, 78, 93, 92, 90, 85},
                    new int[] {88, 85, 90, 88, 90, 88, 90, 85, 88}
             });

            score_table.Add("炮",
             new int[][]
             {
                    new int[] {100, 100,  96, 91,  90, 91,  96, 100, 100},
                    new int[] { 98,  98,  96, 92,  89, 92,  96,  98,  98},
                    new int[] { 97,  97,  96, 91,  92, 91,  96,  97,  97},
                    new int[] { 96,  99,  99, 98, 100, 98,  99,  99,  96},
                    new int[] { 96,  96,  96, 96, 100, 96,  96,  96,  96},

                    new int[] { 95,  96,  99, 96, 100, 96,  99,  96,  95},
                    new int[] { 96,  96,  96, 96,  96, 96,  96,  96,  96},
                    new int[] { 97,  96, 100, 99, 101, 99, 100,  96,  97},
                    new int[] { 96,  97,  98, 98,  98, 98,  98,  97,  96},
                    new int[] { 96,  96,  97, 99,  99, 99,  97,  96,  96 }
             });

        }
        //深拷贝一份PieceList
        public static List<Piece> CopyList(List<Piece> pl)
        {
            List<Piece> pies = new List<Piece>();
            foreach (Piece p in pl)
            {
                Type t = p.GetType();
                var tt = (Piece)Activator.CreateInstance(t, new object[] { p.type, p.xgap, p.ygap });
                tt.setXy(p.X, p.Y);
                pies.Add(tt);
            }
            return pies;
        }
        //深拷贝一份Piece
        public static Piece CopyPiece(Piece p)
        {
            Type t = p.GetType();
            var tt = (Piece)Activator.CreateInstance(t, new object[] { p.type, p.xgap, p.ygap });
            tt.setXy(p.X, p.Y);
            return p;
        }
    }
}
